package com.macro.mall.commission.service.impl;

import com.macro.mall.commission.enums.AssignTypeEnum;
import com.macro.mall.commission.props.AssignPercentProperties;
import com.macro.mall.commission.service.AssignService;
import com.macro.mall.commission.service.AssignUserGroupResolver;
import com.macro.mall.commission.service.bo.AssignItemBo;
import com.macro.mall.commission.service.bo.AssignOrder;
import com.macro.mall.commission.service.bo.AssignUserGroup;
import com.macro.mall.common.api.util.BigDecimalUtils;
import com.macro.mall.oms.entity.OrderEntity;
import com.macro.mall.oms.service.order.OrderService;
import com.macro.mall.ums.entity.MemberEntity;
import com.macro.mall.ums.service.account.MemberService;
import com.macro.mall.ums.service.account.bo.UpdateMemberInput;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * 佣金分配服务
 *
 * @author xuyanjun
 * @date 2019-07-22
 */
@Service
public class AssignServiceImpl implements AssignService {

    @Autowired
    private OrderService liveOrderService;

    @Autowired
    private AssignUserGroupResolver assignUserGroupResolver;

    @Autowired
    private AssignPercentProperties assignPercentProperties;

    @Autowired
    private MemberService memberService;

    /**
     * 获取分佣集合
     *
     * @return 分佣集合
     */
    @Override
    public List<AssignItemBo> listAssignItem(long orderId, int calculateType) {
        AssignOrder assignOrder = getAssignOrderByOrderSource(orderId, calculateType);
        Assert.notNull(assignOrder, "订单id:" + orderId + " 不存在。");

        checkAssignPercent();

        AssignUserGroup assignUserGroup = assignUserGroupResolver.resolve(assignOrder.getAssignStartUserId());

        List<AssignItemBo> result = new ArrayList<>();

        AssignItemBo waiter1AssignItem = createWaiter1AssignItem(assignUserGroup, assignOrder);
        AssignItemBo waiter2AssignItem = createWaiter2AssignItem(assignUserGroup, assignOrder);

        AssignItemBo shopKeeper1AssignItem = createShopKeeper1AssignItem(assignUserGroup, assignOrder);
        AssignItemBo shopKeeper2AssignItem = createShopKeeper2AssignItem(assignUserGroup, assignOrder);

        AssignItemBo shopOwner1AssignItem = createShopOwner1AssignItem(assignUserGroup, assignOrder);
        AssignItemBo shopOwner2AssignItem = createShopOwner2AssignItem(assignUserGroup, assignOrder);

        AssignItemBo tk = createTkAssignItem(assignUserGroup, assignOrder);

        if (waiter1AssignItem != null) {
            result.add(waiter1AssignItem);
        }
        if (waiter2AssignItem != null) {
            result.add(waiter2AssignItem);
        }
        if (shopKeeper1AssignItem != null) {
            result.add(shopKeeper1AssignItem);
        }
        if (shopKeeper2AssignItem != null) {
            result.add(shopKeeper2AssignItem);
        }
        if (shopOwner1AssignItem != null) {
            result.add(shopOwner1AssignItem);
        }
        if (shopOwner2AssignItem != null) {
            result.add(shopOwner2AssignItem);
        }
        if (tk != null) {
            result.add(tk);
        }
        return result;
    }

    /**
     * 检查分佣比例
     */
    private void checkAssignPercent() {
        if (assignPercentProperties == null) {
            throw new IllegalArgumentException("没有找到分佣比例配置。");
        }

        BigDecimal totalPercent = BigDecimal.ZERO;
        if (assignPercentProperties.getWaiter1Percent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getWaiter1Percent());
        }
        if (assignPercentProperties.getWaiter2Percent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getWaiter2Percent());
        }
        if (assignPercentProperties.getShopKeeper1Percent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getShopKeeper1Percent());
        }
        if (assignPercentProperties.getShopKeeper2Percent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getShopKeeper2Percent());
        }
        if (assignPercentProperties.getShopOwner1Percent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getShopOwner1Percent());
        }
        if (assignPercentProperties.getShopOwner2Percent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getShopOwner2Percent());
        }
        if (assignPercentProperties.getTkPercent() != null) {
            totalPercent = totalPercent.add(assignPercentProperties.getTkPercent());
        }

        BigDecimal maxPercent = new BigDecimal(200);

        Assert.isTrue(maxPercent.compareTo(totalPercent) >= 0, "分佣比例总和不能超过200。");
    }

    /**
     * 根据订单来源获取分佣订单
     *
     * @param orderId 订单id
     * @return 分佣订单
     */
    private AssignOrder getAssignOrderByOrderSource(long orderId, int calculateType) {
        AssignOrder assignOrder;

        OrderEntity liveOrderEntity = liveOrderService.getById(orderId);
        Assert.notNull(liveOrderEntity, "订单id:" + orderId + "不存在。");
        assignOrder = convertLiveOrderToAssignOrder(liveOrderEntity, calculateType);
        return assignOrder;
    }

    /**
     * 将生活订单转换成分佣订单
     *
     * @param order 生活订单
     * @return 分佣订单
     */
    private AssignOrder convertLiveOrderToAssignOrder(OrderEntity order, int calculateType) {
        AssignOrder assignOrder = new AssignOrder();
        assignOrder.setOrderId(order.getId())
                .setOrderNo(order.getOrderSn())
                .setUserId(order.getMemberId())
                .setAssignStartUserId(order.getMemberId())
                .setUserName(order.getMemberUsername())
                .setOrderAmount(BigDecimalUtils.fromYuanToFeng(order.getPayAmount()))
                .setCommission(calculateType == 1 ? BigDecimalUtils.fromYuanToFeng(order.getSettlePrice()) : BigDecimalUtils.fromYuanToFeng(order.getPredicatePrice()))
                .setPaymentTime(order.getPaymentTime())
                .setCompleteTime(order.getReceiveTime());

        if (1 == calculateType && order.getPayAmount().compareTo(new BigDecimal("520")) >= 0) {
            MemberEntity memberEntity = memberService.getById(order.getMemberId());
            if (memberEntity.getLevel() == 0) {
                UpdateMemberInput updateMemberInput = new UpdateMemberInput();
                updateMemberInput.setId(order.getMemberId())
                        .setLevel(1);
                memberService.update(updateMemberInput);

                List<MemberEntity> userChain = assignUserGroupResolver.resolveUserChain(order.getMemberId());
                if (userChain.size() > 1) {
                    assignOrder.setAssignStartUserId(userChain.get(1).getId());
                }
            }
        }

        return assignOrder;
    }

    /**
     * 小二1
     */
    private AssignItemBo createWaiter1AssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity waiter1;
        if (userGroup.getWaiter1() != null) {
            waiter1 = userGroup.getWaiter1();
        } else {
            waiter1 = getTkUser(userGroup);
            assignItemBo.setRemark("淘客身份");
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, waiter1, AssignTypeEnum.WAITER_1);

        assignItemBo.setPercent(assignPercentProperties.getWaiter1Percent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getWaiter1Percent()));

        return assignItemBo;
    }

    /**
     * 小二2
     */
    private AssignItemBo createWaiter2AssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity waiter2;
        if (userGroup.getWaiter2() != null) {
            waiter2 = userGroup.getWaiter2();
        } else {
            waiter2 = getTkUser(userGroup);
            assignItemBo.setRemark("淘客身份");
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, waiter2, AssignTypeEnum.WAITER_2);

        assignItemBo.setPercent(assignPercentProperties.getWaiter2Percent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getWaiter2Percent()));

        return assignItemBo;
    }

    /**
     * 掌柜1
     */
    private AssignItemBo createShopKeeper1AssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity shopKeeper1;
        if (userGroup.getShopKeeper1() != null) {
            shopKeeper1 = userGroup.getShopKeeper1();
        } else {
            shopKeeper1 = getTkUser(userGroup);
            assignItemBo.setRemark("淘客身份");
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, shopKeeper1, AssignTypeEnum.SHOP_KEEPER_1);

        assignItemBo.setPercent(assignPercentProperties.getShopKeeper1Percent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getShopKeeper1Percent()));

        return assignItemBo;
    }

    /**
     * 掌柜2
     */
    private AssignItemBo createShopKeeper2AssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity shopKeeper2;
        if (userGroup.getShopKeeper2() != null) {
            shopKeeper2 = userGroup.getShopKeeper2();
        } else {
            shopKeeper2 = getTkUser(userGroup);
            assignItemBo.setRemark("淘客身份");
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, shopKeeper2, AssignTypeEnum.SHOP_KEEPER_2);

        assignItemBo.setPercent(assignPercentProperties.getShopKeeper2Percent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getShopKeeper2Percent()));

        return assignItemBo;
    }

    /**
     * 店长1
     */
    private AssignItemBo createShopOwner1AssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity shopOwner1;
        if (userGroup.getShopOwner1() != null) {
            shopOwner1 = userGroup.getShopOwner1();
        } else {
            shopOwner1 = getTkUser(userGroup);
            assignItemBo.setRemark("淘客身份");
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, shopOwner1, AssignTypeEnum.SHOP_OWNER_1);

        assignItemBo.setPercent(assignPercentProperties.getShopOwner1Percent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getShopOwner1Percent()));

        return assignItemBo;
    }

    /**
     * 店长2
     */
    private AssignItemBo createShopOwner2AssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity shopOwner2;
        if (userGroup.getShopOwner2() != null) {
            shopOwner2 = userGroup.getShopOwner2();
        } else {
            shopOwner2 = getTkUser(userGroup);
            assignItemBo.setRemark("淘客身份");
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, shopOwner2, AssignTypeEnum.SHOP_OWNER_2);

        assignItemBo.setPercent(assignPercentProperties.getShopOwner2Percent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getShopOwner2Percent()));

        return assignItemBo;
    }

    /**
     * tk
     */
    private AssignItemBo createTkAssignItem(AssignUserGroup userGroup, AssignOrder assignOrder) {
        AssignItemBo assignItemBo = new AssignItemBo();

        MemberEntity tk;
        if (userGroup.getTk() != null) {
            tk = userGroup.getTk();
        } else {
            tk = getTkUser(userGroup);
        }

        fillOrderFields(assignItemBo, assignOrder);
        fillUserFields(assignItemBo, tk, AssignTypeEnum.TK);

        assignItemBo.setPercent(assignPercentProperties.getTkPercent());
        assignItemBo.setAmount(calculateCommission(assignOrder.getCommission(), assignPercentProperties.getTkPercent()));

        return assignItemBo;
    }

    /**
     * 填充订单字段
     *
     * @param assignItemBo item
     * @param order        分佣订单
     */
    private void fillOrderFields(AssignItemBo assignItemBo, AssignOrder order) {
        assignItemBo.setOrderId(order.getOrderId())
                .setOrderNo(order.getOrderNo())
                .setOrderAmount(order.getOrderAmount())
                .setOrderUserId(order.getUserId())
                .setOrderUserName(order.getUserName())
                .setOrderPaymentTime(order.getPaymentTime())
                .setOrderCompleteTime(order.getCompleteTime());
    }

    /**
     * 填充用户字段
     *
     * @param assignItemBo   item
     * @param user           用户
     * @param assignTypeEnum 分佣类型
     */
    private void fillUserFields(AssignItemBo assignItemBo, MemberEntity user, AssignTypeEnum assignTypeEnum) {
        assignItemBo.setUserId(user.getId());
        assignItemBo.setUserName(user.getNickname());
        assignItemBo.setAssignType(assignTypeEnum.getValue());
        assignItemBo.setAssignTypeName(assignTypeEnum.getDescription());
    }

    /**
     * 创建空用户
     *
     * @return 空用户
     */
    private MemberEntity getTkUser(AssignUserGroup assignUserGroup) {
        if (assignUserGroup.getTk() != null) {
            return assignUserGroup.getTk();
        }

        MemberEntity user = new MemberEntity();
        user.setId(0L);
        user.setNickname("");

        return user;
    }

    /**
     * 计算佣金
     *
     * @param commission 佣金
     * @param percent    百分比例
     * @return 佣金
     */
    private Integer calculateCommission(Integer commission, BigDecimal percent) {
        percent = percent.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);

        int value = new BigDecimal(commission).multiply(percent).setScale(0, RoundingMode.HALF_UP).intValue();
        return value;
    }

}
